package com.wuyb.socket;

import com.alibaba.fastjson2.JSONObject;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.wuyb.pojo.User;
import com.wuyb.service.ChatFilterService;
import com.wuyb.service.MeetingChatService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * Socket连接
 *
 * @Author: wyb
 * @Date: 2024/01/03/15:02
 * @Description:
 */
@Component
@Slf4j
public class SocketSender {

    @Resource
    private SocketIOServer socketIOServer;

    @Resource
    private ChatFilterService chatFilterService;

    @Resource
    private MeetingChatService meetingChatService;

    @Resource
    private SocketMapDao socketMapDao;


    /**
     * 发送执行指令给会议某用户执行
     *
     * @param actionType
     * @param meetId
     * @param userId
     * @param msg
     * @param without
     */
    public void sendActionToMeetUser(String actionType, String meetId, Integer userId, String msg, boolean without) {
        Map<String, Object> map = new HashMap<>();
        map.put("type", actionType);
        map.put("msg", msg);
        if (without) {
            sendMeetWithoutId(userId, meetId, "action", map);
        } else {
            sendMeetById(userId, meetId, "action", map);
        }
    }


    /**
     * 发送给该房间中除此ID以外的人(广播模式)
     *
     * @param userId
     * @param meetingId
     * @param event
     * @param data
     */
    private void sendMeetWithoutId(Integer userId, String meetingId, String event, Object data) {
        Collection<SocketIOClient> clients = socketIOServer.getRoomOperations(meetingId).getClients();
        for (SocketIOClient c : clients) {
            if (!socketMapDao.getSocketUserByUUID(c.getSessionId()).users.getId().equals(userId)) {
                c.sendEvent(event, data);
            }
        }
    }


    /**
     * 发送给该房间中该ID的人（点对点）
     *
     * @param userId
     * @param meetingId
     * @param event
     * @param data
     */
    public void sendMeetById(Integer userId, String meetingId, String event, Object data) {
        Collection<SocketIOClient> clients = socketIOServer.getRoomOperations(meetingId).getClients();
        for (SocketIOClient c : clients) {
            if (socketMapDao.getSocketUserByUUID(c.getSessionId()).users.getId().equals(userId)) {
                c.sendEvent(event, data);
                return;
            }
        }
    }


    /**
     * 发送用户的开麦投屏状态给房间里所有人包括自己
     *
     * @param meetId
     * @param userId
     * @param uping
     * @param speeching
     */
    public void sendStateToMeetUser(String meetId, Integer userId, Boolean uping, Boolean speeching) {
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("uping", uping);
        map.put("speeching", speeching);
        sendMeetAll(meetId, "updateState", map);
    }


    /**
     * 发送给该会议中的所有人
     * @param meetingId
     * @param event
     * @param data
     */
    private void sendMeetAll(String meetingId, String event, Object data) {
        Collection<SocketIOClient> clients = socketIOServer.getRoomOperations(meetingId).getClients();
        for (SocketIOClient c : clients) {
            c.sendEvent(event, data);
        }
    }


    /**
     * 发送通知消息给对面
     * @param data
     * @param way   1、好友申请通知， 2、会议申请通知， 3、会议公告通知
     * @param toId
     */
    public void sendInform(JSONObject data, Integer way, Integer toId) {
        data.put("toId", toId);
        sendInform(data, way);
    }


    public void sendInform(JSONObject data, Integer way) {
        data.put("way", way);
        sendMessage("updateInform", data);
    }


    /**
     * 发送聊天消息给对面
     * @param data
     */
    public void sendChat(JSONObject data) {
        sendMessage("friendChat",data);
    }


    /**
     * 消息发送给用户
     * @param event
     * @param data
     */
    private void sendMessage(String event, JSONObject data) {
        Integer toId = data.getInteger("toId");
        SocketUser socketUser = socketMapDao.getSocketUserByUserId(toId);
        if (socketUser == null) {
            return ;
        }
        log.info((String.format("socket:事件: %s,sessionId:%s,对象：%s，data：%s", event, socketUser.client.getSessionId(), socketUser.users, data)));
        socketUser.client.sendEvent(event, data);
    }


    /**
     * 以系统身份向聊天框发送消息
     * @param meetingId
     * @param message
     */
    public void sendMeetChatBySys(String meetingId, String message) {
        User user = new User().setId(-1).setName("sys");
        JSONObject data = new JSONObject();
        data.put("msg",message);
        sendMeetChat(meetingId,user,data);
    }


    /**
     * 向聊天室发送消息
     * @param meetingId
     * @param user
     * @param data
     */
    public void sendMeetChat(String meetingId, User user, JSONObject data) {
        data.put("user", user);
        String msg = chatFilterService.filter(data.getString("msg"));
        data.put("msg",msg);
        if (user.getId() > 0) {
            meetingChatService.insert(meetingId,user.getId(), msg);
        }
        socketIOServer.getRoomOperations(meetingId).sendEvent("meetchat",data);
    }


    /**
     * 通过SessionId获取用户Id
     * @param sessionId
     * @return
     */
    public Integer getUserIdBySession(UUID sessionId) {
        return socketMapDao.getSocketUserByUUID(sessionId).users.getId();
    }


    /**
     * 通过会议获取当前房间的用户列表
     * @param meetingId
     * @return
     */
    public List<User> getUserListByMeetId(String meetingId) {
        List<User> userList = new ArrayList<>();
        socketIOServer.getRoomOperations(meetingId).getClients().forEach(x -> userList.add(socketMapDao.getSocketUserByUUID(x.getSessionId()).users));
        return userList;
    }


    /**
     * 将房间的用户消息发送给刚加入会议的人
     * @param meetingId
     * @param userId
     */
    public void sendUserListById(String meetingId, Integer userId) {
        List<User> userListByMeetId = getUserListByMeetId(meetingId);
        sendMeetById(userId, meetingId, "meeting_users", userListByMeetId);
    }


    /**
     * 将房间用户信息发送给其他人
     * @param meetingId
     * @param client
     */
    public void sendUserListWithout(String meetingId, SocketIOClient client) {
        List<User> userList = getUserListByMeetId(meetingId);
        sendMeetWithout(client, meetingId, "meeting_users", userList);
    }

    /**
     * 发送给房间里的其他人
     * @param client
     * @param meetingId
     * @param event
     * @param data
     */
    public void sendMeetWithout(SocketIOClient client, String meetingId, String event, Object data) {
        Collection<SocketIOClient> clients = socketIOServer.getRoomOperations(meetingId).getClients();
        for (SocketIOClient c : clients) {
            if (c.getSessionId() != client.getSessionId()) {
                c.sendEvent(event, data);
            }
        }
    }


    /**
     * 是否存在于会议当中
     * @param meetingId
     * @param client
     * @return
     */
    public boolean isExist(String meetingId, SocketIOClient client) {
        Collection<SocketIOClient> clients = socketIOServer.getRoomOperations(meetingId).getClients();
        for (SocketIOClient c : clients) {
            if (c.getSessionId() == client.getSessionId()) {
                return true;
            }
        }
        return false;
    }


}
